pub mod channel_setting_router;
pub mod common_router;
pub mod device_router;
pub mod dto;
pub mod hot_update_setting_router;
pub mod whitelist_router;

use crate::custom_filter::CustomFilter;
use std::convert::Infallible;
use std::sync::Arc;
use tracing::error;
use tracing::trace;
use warp::hyper::StatusCode;
use warp::reply::with_status;
use warp::{Filter, Rejection, Reply, log};

fn handle_other() -> impl Filter<Extract = (impl Reply,), Error = Infallible> + Clone {
    warp::any().map(|| with_status("Not Found", StatusCode::NOT_FOUND))
}

fn log_request(info: log::Info) {
    let path = info.path();
    let method = info.method().to_string();
    let remote_ip = info
        .remote_addr()
        .map_or("None".to_string(), |addr| addr.ip().to_string());
    let status = info.status().to_string();
    let elapsed = info.elapsed().as_millis();

    trace!(
        %path,
        %method,
        %remote_ip,
        %status,
        %elapsed,
        "Handled a request",
    );

    if info.status() != StatusCode::OK {
        error!(
            %path,
            %method,
            %remote_ip,
            %status,
            %elapsed,
            "Not ok"
        );
    }
}

pub fn get_all_router(
    filter: Arc<CustomFilter>,
) -> impl warp::Filter<Extract = (impl Reply,), Error = Rejection> + Clone {
    common_router::get_all_router(filter.clone())
        .or(channel_setting_router::get_all_router(filter.clone()))
        .or(hot_update_setting_router::get_all_router(filter.clone()))
        .or(whitelist_router::get_all_router(filter.clone()))
        .or(device_router::get_all_router(filter.clone()))
        .or(handle_other())
        .with(filter.cors())
        .with(log::custom(log_request))
}
